/**
 * Created by baidm in 2022/1/9 on 8:58
 */

/**
 * ref
 * @param target
 * @returns {{_is_ref: boolean, _value, value}|*}
 */
function ref(target) {
  target = reactive(target);

  return {
    _is_ref: true,
    _value: target,
    get value() {
      return this._value;
    },
    set value(val) {
      this._value = val;
    }
  }
}

/**
 * shallowRef
 * @param target
 * @returns {{_value, value}|*}
 */
function shallowRef(target) {
  return {
    // 临时存储target
    _value: target,
    get value() {
      return this._value;
    },
    set value(val) {
      this._value = val;
    }
  }
}

/**
 * reactive
 * @param target
 * @returns {*}
 */
function reactive(target) {
  // 判断target是否是对象或数组
  if (target && typeof target === "object") {

    if (Array.isArray(target)) {
      // 数组的数据进行遍历递归操作
      target.forEach((item, index) => {
        target[index] = reactive(item);
      })
    } else {
      // 对象的数据进行遍历操作
      Object.keys(target).forEach(key => {
        target[key] = reactive(target[key]);
      })
    }

    return new Proxy(target, reactiveHandler)
  }

  return target
}

/**
 * shallowReactive
 * @param target
 * @returns {*}
 */
function shallowReactive(target) {
  // 判断target是否是对象或数组
  if (target && typeof target === "object") {
    return new Proxy(target, reactiveHandler)
  }

  return target
}

const reactiveHandler = {
  get(target, prop) {
    if (prop === "_is_reactive") return true;
    return Reflect.get(target, prop)
  },
  set(target, prop, value) {
    return Reflect.set(target, prop, value)
  },
  deleteProperty(target, prop) {
    return Reflect.deleteProperty(target, prop)
  }
};

/**
 * readonly
 * @param target
 * @returns {*}
 */
function readonly(target) {
  // 判断target是否是对象或数组
  if (target && typeof target === "object") {
    if (Array.isArray(target)) {
      target.forEach((item, index) => {
        target[index] = readonly(item);
      })
    } else {
      Object.keys(target).forEach(key => {
        target[key] = readonly(target[key]);
      })
    }

    return new Proxy(target, readonlyHandler);
  }

  return target;
}

/**
 * shallowReadonly
 * @param target
 * @returns {*}
 */
function shallowReadonly(target) {
  // 判断target是否是对象或数组
  if (target && typeof target === "object") {
    return new Proxy(target, readonlyHandler);
  }

  return target;
}

const readonlyHandler = {
  get(target, prop) {
    if (prop === "_is_readonly") return true;
    return Reflect.get(target, prop);
  },
  set(target, prop, value) {
    console.warn("只读对象不可设置");
    return true;
  },
  deleteProperty(target, prop) {
    console.warn("只读对象不可删除");
    return true;
  }
};

/**
 * isRef
 * @param obj
 * @returns {boolean}
 */
function isRef(obj) {
  return obj && obj._is_ref;
}

/**
 * isReactive
 * @param obj
 * @returns {*}
 */
function isReactive(obj) {
  return obj && obj._is_reactive;
}

/**
 * isReadonly
 * @param obj
 * @returns {*}
 */
function isReadonly(obj) {
  return obj && obj._is_readonly;
}

/**
 * isProxy
 * @param obj
 * @returns {*}
 */
function isProxy(obj) {
  return isReactive(obj) || isReadonly(obj);
}